package com.zackeus.mvvm.api;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.liulishuo.okdownload.DownloadListener;
import com.liulishuo.okdownload.DownloadTask;
import com.liulishuo.okdownload.OkDownload;
import com.zackeus.common.utils.ObjectUtils;
import com.zackeus.common.utils.Utils;

/**
 * 文件下载引擎管理器
 * @name: DownloadManager
 * @author: zz
 * @date: 2022/11/15
 */
public class DownloadManager {

    public static final int CALLBACK_PROCESS = 100;

    private static volatile DownloadManager mInstance;

    /* 默认下载文件保存目录 */
    private final String defaultDir;

    private DownloadManager() {
        defaultDir = Utils.getContext().getExternalFilesDir(null).getPath() + "/download";
    }

    public static DownloadManager getInstance() {
        if (mInstance == null) {
            synchronized (DownloadManager.class) {
                if (mInstance == null) {
                    mInstance = new DownloadManager();
                }
            }
        }
        return mInstance;
    }

    public DownloadTask doTask(@NonNull String url, @NonNull String filename, @NonNull DownloadListener listener) {
        return this.doTask(url, this.defaultDir, filename, null, listener);
    }

    public DownloadTask doTask(@NonNull String url, @NonNull String filename,
                               @Nullable Object tag, @NonNull DownloadListener listener) {
        return this.doTask(url, this.defaultDir, filename, tag, listener);
    }

    /**
     * 执行下载任务
     * @param url 下载文件URL
     * @param parentPath 文件保存目录
     * @param filename 文件保存名
     * @param tag 任务标识(用于断点续传)
     * @param listener 文件下载状态监听器
     * @return
     */
    public DownloadTask doTask(@NonNull String url, @NonNull String parentPath, @NonNull String filename,
                               @Nullable Object tag, @NonNull DownloadListener listener) {
        DownloadTask.Builder builder = new DownloadTask.Builder(url, parentPath, filename)
                /* 设置下载文件名，没提供的话先看 response header ，再看 url path(即启用下面那项配置) */
                .setFilename(filename)
                /* 是否使用 response header or url path 作为文件名，此时会忽略指定的文件名，默认false */
                .setFilenameFromResponse(Boolean.FALSE)
                /* 如果文件已经下载完成，再次下载时，是否忽略下载，默认为true(忽略)，设为false会从头下载 */
                .setPassIfAlreadyCompleted(Boolean.TRUE)
                /* 需要用几个线程来下载文件，默认根据文件大小确定；如果文件已经 split block，则设置后无效 */
                .setConnectionCount(1)
                /* 在获取资源长度后，设置是否需要为文件预分配长度，默认false */
                .setPreAllocateLength(Boolean.FALSE)
                /* 通知调用者的频率，避免anr，默认3000 ms */
                .setMinIntervalMillisCallbackProcess(CALLBACK_PROCESS)
                /* 是否只允许wifi下载，默认为false */
                .setWifiRequired(Boolean.FALSE)
                /* 是否在主线程通知调用者，默认为true */
                .setAutoCallbackToUIThread(Boolean.TRUE)
                /* 设置优先级，默认值是0，值越大下载优先级越高 */
                .setPriority(0);
        /* 追加请求头 */
        /* Accept-Encoding 解决download onProgress 回调 total 为0 */
        builder.addHeader("Accept-Encoding", "*");
        return this.doTask(tag, builder, listener);
    }

    public DownloadTask doTask(@NonNull DownloadTask.Builder builder, @NonNull DownloadListener listener) {
        return this.doTask(null, builder, listener);
    }

    /**
     * 执行下载任务
     * @param tag 任务标识(用于断点续传)
     * @param builder 任务构造器
     * @param listener 文件下载状态监听器
     * @return
     */
    public DownloadTask doTask(@Nullable Object tag, @NonNull DownloadTask.Builder builder,
                               @NonNull DownloadListener listener) {
        DownloadTask task = builder.build();
        if (ObjectUtils.isNotEmpty(tag)) {
            task.setTag(tag);
        }
        task.enqueue(listener);
        return task;
    }

    /**
     * 停止并清除下载任务
     * @param taskId 任务ID
     */
    public void clearTask(int taskId) {
        OkDownload.with().downloadDispatcher().cancel(taskId);
        OkDownload.with().breakpointStore().remove(taskId);
    }

}
